package com.ldf.callback;

import com.ldf.core.HCNetSDK;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.ByteByReference;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;


public class FRealDataCallbackForRtp implements HCNetSDK.FRealDataCallBack_V30 {
    private String host;
    private Integer rtpPort;
    private Socket socket;
    private OutputStream outputStream;
    private int seqNum = 0;
    private int timestamp = 0;

    public FRealDataCallbackForRtp(String host, Integer rtpPort) {
        this.rtpPort = rtpPort;
        this.host = host;
        try {
            //先连接服务器，IP地址"localhost"即为本机，“8888”为端口号
            socket = new Socket(host, rtpPort);
            //连接上服务器直接向服务器发送消息
            outputStream = socket.getOutputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void invoke(long lRealHandle, int dwDataType, ByteByReference pBuffer, int dwBufSize, Pointer pUser) throws IOException {

        //ps封装
        if (dwDataType == HCNetSDK.NET_DVR_STREAMDATA) {
            byte[] rtpPacket = new byte[1456];
            //ps
            byte pt = 96;
            //以25帧算 以90000采样 需要自己作重置
            timestamp += 3600;
            byte[] timestampBytes = intToBytes(timestamp);
            //自定义同步源
            byte[] ssrc = new byte[]{0x00, 0x00, 0x00, 0x01};
            byte[] rtpHeader = new byte[]{0x00, 0x00, (byte) 0x80, (byte) (pt & 0xFF), 0x00, 0x00, timestampBytes[0], timestampBytes[1], timestampBytes[2], timestampBytes[3], ssrc[0], ssrc[1], ssrc[2], ssrc[3]};
            System.arraycopy(rtpHeader, 0, rtpPacket, 0, rtpHeader.length);
            int datasize = dwBufSize;
            int offset = 0;
            int useDataSize = rtpPacket.length - rtpHeader.length;
            while (datasize > 0) {
                byte[] seqNumBytes = shortToBytes(++seqNum);
                if (datasize <= useDataSize) {
                    pBuffer.getPointer().read(offset, rtpPacket, rtpHeader.length, datasize);
                    byte[] dataLengthBytes = shortToBytes(rtpHeader.length + datasize - 2);
                    rtpPacket[0] = dataLengthBytes[0];
                    rtpPacket[1] = dataLengthBytes[1];
                    rtpPacket[3] = (byte) (rtpPacket[3] | 0x80);
                    rtpPacket[4] = seqNumBytes[0];
                    rtpPacket[5] = seqNumBytes[1];
                    outputStream.write(rtpPacket, 0, rtpHeader.length + datasize);
                    outputStream.flush();
                    break;
                } else {
                    pBuffer.getPointer().read(offset, rtpPacket, rtpHeader.length, useDataSize);
                    byte[] dataLengthBytes = shortToBytes(rtpPacket.length - 2);
                    rtpPacket[0] = dataLengthBytes[0];
                    rtpPacket[1] = dataLengthBytes[1];
                    rtpPacket[4] = seqNumBytes[0];
                    rtpPacket[5] = seqNumBytes[1];
                    outputStream.write(rtpPacket);
                    outputStream.flush();
                    offset += useDataSize;
                    datasize -= useDataSize;
                }
            }
        }
    }

    /**
     * 将int值转换为4字节的字节数组 大端序
     *
     * @param value 要转换的int值
     * @return 包含该int值的4字节表示形式的字节数组
     */
    public static byte[] intToBytes(int value) {
        return new byte[]{
                (byte) (value >>> 24),
                (byte) (value >>> 16),
                (byte) (value >>> 8),
                (byte) value
        };
    }

    /**
     * 将int值转换为4字节的字节数组 大端序
     *
     * @param value 要转换的int值
     * @return 包含该int值的4字节表示形式的字节数组
     */
    public static byte[] shortToBytes(int value) {
        return new byte[]{
                (byte) (value >>> 8),
                (byte) value
        };
    }

}